(*
 * Copyright (C) 2012  INRIA and Microsoft Corporation
 *)

open Printf
open Scanf

(* Change the following two lines for a new version *)
let major = 1
let minor = 4

(* The rest of the file has no magic numbers *)

let same_version = ref false
let loud = ref true
let release = ref false
let rv_exists = Sys.file_exists "src/release_version.ml"

let arglist = [
  "-same", Arg.Set same_version, "don't update version strings";
  "-quiet", Arg.Clear loud, "do not print any messages";
  "-release", Arg.Set release, "tag this version as the released version";
]

let () = Arg.parse arglist (fun _ -> ()) ""

let () =
  let f = open_in "src/version.ml" in
  let (oldmajor, oldminor, oldmicro) =
    try
      ignore (input_line f) ;
      fscanf f
        "let (major,minor,micro) = (%d,%d,%d)"
        (fun oldmajor oldminor oldmicro -> (oldmajor, oldminor, oldmicro))
    with Scan_failure _ ->
      fprintf stderr "Warning: could not parse old version number\n%!";
      (0, 0, 0)
  in
  close_in f ;
  let (major, minor, micro) =
    if !same_version then
      (oldmajor, oldminor, oldmicro)
    else if (major <> oldmajor || minor <> oldminor) then
      (major, minor, 0)
    else
      (major, minor, oldmicro + 1)
  in
  if not rv_exists then failwith "src/release_version.ml does not exist";
  let f = open_in "src/release_version.ml" in
  let (oldrmajor, oldrminor, oldrmicro) =
    try
      ignore (input_line f) ;
      fscanf f
        "let (major,minor,micro) = (%d,%d,%d)"
        (fun oldrmajor oldrminor oldrmicro ->
           (oldrmajor, oldrminor, oldrmicro))
    with Scan_failure _ ->
      fprintf stderr "Warning: could not parse old release version number\n%!";
      (0, 0, 0)
  in
  close_in f;
  let version = Printf.sprintf "%d.%d.%d" major minor micro in
  if !loud then printf "Next version will be: %s\n%!" version;
  let release_version =
    if !release
    then version
    else Printf.sprintf "%d.%d.%d" oldrmajor oldrminor oldrmicro
  in

  let f = open_out "src/version.ml" in
  fprintf f "(* AUTOMATICALLY GENERATED by tools/newversion.ml \
             -- DO NOT EDIT *)\n" ;
  fprintf f "let (major,minor,micro) = (%d,%d,%d);;\n" major minor micro;
  fprintf f "Revision.f \"$Rev: 29780 $\";;\n";
  close_out f;

  let f = open_out "src/release_version.ml" in
  fprintf f "(* AUTOMATICALLY GENERATED by tools/newversion.ml \
             -- DO NOT EDIT *)\n" ;
  if !release then begin
    fprintf f "let (major,minor,micro) = (%d,%d,%d);;\n" major minor micro
  end else begin
    fprintf f "let (major,minor,micro) = (%d,%d,%d);;\n"
            oldrmajor oldrminor oldrmicro
  end;
  fprintf f "Revision.f \"$Rev: 29780 $\";;\n";
  close_out f;

  if !loud then printf "Created src/version.ml\n\
                        Created src/release_version.ml\n%!" ;
  let ac_in = open_in "tools/configure.ac.in" in
  let (acf, ac) = Filename.open_temp_file "configure" ".ac" in
  at_exit (fun () -> Sys.remove acf) ;
  let vreg = Str.regexp (Str.quote "@VERSION@") in
  let rvreg = Str.regexp (Str.quote "@RELEASEVERSION@") in
  begin try while true do
    let line = input_line ac_in in
    let line = Str.global_replace vreg version line in
    let line = Str.global_replace rvreg release_version line in
    output_string ac line ; output_string ac "\n" ;
  done with End_of_file -> ()
  end;
  close_in ac_in ;
  close_out ac ;
  let ret = Sys.command ("autoconf -I tools -o configure " ^ acf) in
  if ret <> 0 then failwith "calling autoconf" ;
  if !loud then printf "Created configure\n%!" ;
  flush Pervasives.stdout ;
  if !loud then printf "Now run ./configure to rebuild the Makefile\n%!"
;;
